package com.tangdi.production.mpaychl.service.impl.alipay;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import org.apache.commons.collections.map.LinkedMap;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.tangdi.production.mpaychl.base.service.BaseTranService;
import com.tangdi.production.mpaychl.utils.chuanhua.SignByMD5;
import com.tangdi.production.mpbase.constants.ExcepCode;
import com.tangdi.production.mpbase.constants.MsgCT;
import com.tangdi.production.mpbase.constants.TranCode;
import com.tangdi.production.mpbase.exception.BusinessException;
import com.tangdi.production.mpbase.exception.TranException;
import com.tangdi.production.mpbase.service.UnionfitService;
import com.tangdi.production.mpbase.util.ConfigUtils;
import com.tangdi.production.mpbase.util.DateUtils;
import com.tangdi.production.mpbase.util.HttpUtil;
import com.tangdi.production.mpbase.util.JUtil;
import com.tangdi.production.mpbase.util.MD5;
import com.tangdi.production.mpbase.util.MD5Utils;
import com.tangdi.production.mpbase.util.MapUtils;
import com.tangdi.production.mpbase.util.MoneyUtils;
import com.tangdi.production.mpbase.util.ObjectUtil;
import com.tangdi.production.mpbase.util.ParamValidate;
import com.tangdi.production.mpbase.util.RSAUtil;
import com.tangdi.production.mpbase.util.StringUtil;
import com.tangdi.production.tdbase.util.MD5Util;

/**
 * <b>Alipay</b>交易[外发]渠道公共处理流程接口实现
 * 
 * @author xiejinzhong 2017/01/13
 *
 */
@SuppressWarnings("unused")
@Service("QUICK_Alipay")
public class AlipayServiceImpl implements BaseTranService {
	private static Logger log = LoggerFactory.getLogger(AlipayServiceImpl.class);

	private static Properties myProp = ConfigUtils.loadProperties("mpaychl/conf-chl-properties/Alipay.properties");

	private static String signKeyName = "sign";
	
	private static String charset = "utf-8";
	private static String SignType = "RSA2";
	
	/**支付宝公钥*/
	public static String ALI_PUB_KEY = myProp.getProperty("pub_ali");
	/**默认商户私钥*/
	public static String ALI_PRV_DEFULT = myProp.getProperty("prv_defult");
	
	/** Alipay APP应用ID **/
	public static String ALI_APP_ID = myProp.getProperty("app_id");

	@Override
	public Map<String, Object> execute(Map<String, Object> param) throws TranException {
		log.info("进入自有跳转处理接口 [{}]", param);
		// 路由编码
		String rtrcod = (String) param.get("rtrcod");
		String nodeId = rtrcod;
		if(StringUtil.isEmpty(param.get("merKey"))){
			param.put("merKey",ALI_PRV_DEFULT);
		}
		try {
			// 公共参数设置
			if ("pay".equals(rtrcod)) {// 下单
				return pay(param);
			} else if ("pay_query".equals(rtrcod) || "pay_que".equals(rtrcod)) {// 交易查询
				return payQuery(param);
//			} else if ("withdrawal".equals(rtrcod)) {// 提现
//				return withdrawal(param);
//			} else if ("withdrawalQuery".equals(rtrcod) || "cas_que".equals(rtrcod)) {// 代付结果查询
//				return withdrawalQuery(param);
			} else {
				throw new BusinessException(ExcepCode.EX900003, "不支持的路由编码[{}]", rtrcod);
			}
		} catch (TranException e) {
			throw e;
		} catch (Exception e) {
			e.printStackTrace();
			log.error("渠道调用异常:" + e.getMessage(), e);
			throw new BusinessException(ExcepCode.EX900001, "执行出错");
		}
		// return new HashMap<String, Object>();
	}
	
	public static boolean verifySign(String signKey,Map<String,Object> signMap)throws Exception{
		log.info("验签开始...");
		String chlSign = ObjectUtil.getString(signMap.get(signKeyName));
		log.info("渠道签名[{}]",chlSign);
		
		Map<String, Object> map = new TreeMap<>(signMap);
		map.remove(signKeyName);
		String signStr = MapUtils.getSignStrByMap(map, true);
		log.info("签名原串:[{}]",signStr);
		return RSAUtil.rsa256CheckContent(signStr, chlSign, signKey, charset);
//		return RSAUtil.rsaCheck(signStr, chlSign, signKey, charset);
	}
	public static boolean verifySign(String signKey,String signStr,String chlSign)throws Exception{
		log.info("渠道签名[{}]",chlSign);
		log.info("签名原串:[{}]",signStr);
		return RSAUtil.rsa256CheckContent(signStr, chlSign, signKey, charset);
//		return RSAUtil.rsaCheck(signStr, chlSign, signKey, charset);
	}
	
	public static String sign(String signKey,Map<String,Object> signMap) throws Exception{
		Map<String, Object> map = new TreeMap<>(signMap);
		map.remove(signKeyName);
		String signStr = MapUtils.getSignStrByMap(map, true);
		log.info("签名原串:[{}]",signStr);
		String sign = RSAUtil.rsa256Sign(signStr, signKey, charset);
		log.info("签名结果:[{}]",sign);
		return sign;
	}
	
	private Map<String,Object> sendHttpRequest(String url,Map<String,Object> paramMap) throws Exception{
		Map<String,Object> requestHead = new LinkedHashMap<>();
//		requestHead.put("Content-Type","application/json; charset=UTF-8");
		String resStr = HttpUtil.httpRequest(url, paramMap, HttpUtil.HTTP_METHOD_POST, charset, requestHead);
		log.info("返回[{}]",resStr);
		Map<String,Object> resMap = JUtil.toMap(resStr);
		
		return resMap;
	}
	

	public Map<String, Object> pay(Map<String, Object> param) throws Exception {
		log.info("[Alipay]下单接口:[{}]", param);
		ParamValidate.doing(param, "TMercId","merKey", "prdOrdNo", "payAmt","rateType");
		
		String signKey = (String) param.get("merKey");
		
		Map<String, Object> paramMap = new TreeMap<String, Object>();
		paramMap.put("out_trade_no", param.get("prdOrdNo"));
//		paramMap.put("seller_id", "");//卖家支付宝用户ID。 如果该值为空，则默认为商户签约账号对应的支付宝用户ID
		
		String payAmt = ObjectUtil.getString(param.get("payAmt"));
		log.info("支付金额[{}分]", payAmt);
		payAmt = MoneyUtils.toStrYuan(payAmt);
		log.info("支付金额转换为元[{}]", payAmt);
		
		paramMap.put("total_amount", payAmt);
		paramMap.put("subject", param.get("prdOrdNo"));
//		paramMap.put("body", "商家收款:订单号" + param.get("prdOrdNo"));
		
		String rateType = ObjectUtil.getString(param.get("rateType"));
		log.info("费率类型[{}]",rateType);
		if(MsgCT.RATE_TYPE_ZHIFUBAO_API.equals(rateType)){
			;
		}else if(MsgCT.RATE_TYPE_ZHIFUBAO_H5.equals(rateType) || MsgCT.RATE_TYPE_ZHIFUBAO_H5_API.equals(rateType)){
			;
		}else{
			throw new BusinessException(ExcepCode.EX900000,"不支持的费率类型[{}]",rateType);
		}
		
		Map<String,Object> reqMap = new TreeMap<>();
		if (param.get("TMercId") != null ) {
			reqMap.put("app_id", param.get("TMercId"));////////////////////////
		}
		else{
			reqMap.put("app_id", ALI_APP_ID);
		}
		reqMap.put("method", "alipay.trade.precreate");
		reqMap.put("format", "JSON");
		reqMap.put("charset", charset);
		reqMap.put("sign_type", SignType);
		reqMap.put("timestamp", DateUtils.formatCurrentDateTime(DateUtils.DATETIME_FORMAT_4));
		reqMap.put("version", "1.0");
		reqMap.put("notify_url", myProp.get("pay_call_back_url"));
		reqMap.put("biz_content", JUtil.toJsonString(paramMap));
		reqMap.put(signKeyName, sign(signKey,reqMap));
		
		String url = myProp.getProperty("pay_url");
		
		Map<String,Object> resMap = sendHttpRequest(url, reqMap);
		
		
		Map<String,Object> backMap = new HashMap<>();
		backMap.put("ordStatus", MsgCT.ORDSTATUS_PROCESSING);
		
		Map<String,Object> resTrade = (Map<String,Object>)resMap.get("alipay_trade_precreate_response");
		
		String codeUrl = ObjectUtil.getString(resTrade.get("qr_code"));
		
//		String chlSign = ObjectUtil.getString(resMap.get(signKeyName));
//		String signStr = "alipay_trade_precreate_response=" + JUtil.toJsonString(resTrade).replaceAll("/", "\\/");
//
//		if(!verifySign(ALI_PUB_KEY,signStr, chlSign)){
//			backMap.put("ordStatus", MsgCT.ORDSTATUS_FAIL);
//			backMap.put("msg", "交易验签失败，为了您的交易安全，请重新发起！");
//			return backMap;
//		}
		
		
		
		if(StringUtil.isEmpty(codeUrl)){
			backMap.put("ordStatus", MsgCT.ORDSTATUS_FAIL);
			backMap.put("msg", resTrade.get("msg"));
			backMap.put("isClose", "1");
			backMap.put("desc", resTrade.get("msg"));
		}else{
			if(MsgCT.RATE_TYPE_ZHIFUBAO_H5.equals(rateType) || MsgCT.RATE_TYPE_ZHIFUBAO_H5_API.equals(rateType)){
				String html = MapUtils.getForwardHtml(codeUrl);
//				html = html.replaceAll("method=\"post\"", "method=\"get\"");
				backMap.put("busContent", html);
				backMap.put("contentType", MsgCT.DATA_TYPE_HTML);
				return backMap;
			}
			backMap.put("busContent", codeUrl);
		}

		return backMap;
	}
	
	/**
	 * 交易结果查询
	 * @param param
	 * @return
	 * @throws Exception
	 */
	public Map<String, Object> payQuery(Map<String, Object> param)
			throws Exception {
		log.info("[Alipay]支付结果查询调用:" + param);
		// 参数非空验证
		ParamValidate.doing(param, "TMercId","merKey","prdOrdNo");

		String orderNo = (String) param.get("prdOrdNo");

		String signKey = (String) param.get("merKey");
		
		Map<String, Object> paramMap = new TreeMap<String, Object>();
		paramMap.put("out_trade_no", orderNo);
		
		Map<String,Object> reqMap = new TreeMap<>();
		if (param.get("TMercId") != null ) {
			reqMap.put("app_id", param.get("TMercId"));////////////////////////
		}
		else{
			reqMap.put("app_id", ALI_APP_ID);
		}
		//reqMap.put("app_id", param.get("TMercId"));//
		reqMap.put("method", "alipay.trade.query");
		reqMap.put("format", "JSON");
		reqMap.put("charset", charset);
		reqMap.put("sign_type", SignType);
		reqMap.put("timestamp", DateUtils.formatCurrentDateTime(DateUtils.DATETIME_FORMAT_4));
		reqMap.put("version", "1.0");
		reqMap.put("notify_url", myProp.get("pay_call_back_url"));
		reqMap.put("biz_content", JUtil.toJsonString(paramMap));
		reqMap.put(signKeyName, sign(signKey,reqMap));
		
		String url = myProp.getProperty("pay_url");
		
		Map<String,Object> resMap = sendHttpRequest(url, reqMap);
		
		
		Map<String,Object> backMap = new HashMap<>();
		backMap.put("ordStatus", MsgCT.ORDSTATUS_PROCESSING);
		
		Map<String,Object> resTrade = (Map<String,Object>)resMap.get("alipay_trade_query_response");
		String status = ObjectUtil.getString(resTrade.get("trade_status"));
		log.info("交易状态[{}]",status);
		if("TRADE_SUCCESS".equals(status)){
			backMap.put("ordStatus", MsgCT.ORDSTATUS_SUCCESS);
		}
		return backMap;
	}

	/**
	 * 提现
	 * 
	 * @param param
	 * @return
	 * @throws Exception
	 */
	public Map<String, Object> withdrawal(Map<String, Object> param) throws Exception {
		log.info("[Alipay]提现调用:" + param);
		// 参数非空验证
		ParamValidate.doing(param, "TMercId","merKey","casOrdNo", "netrecAmt","cardNo","accountName");

		String orderNo = (String) param.get("casOrdNo");
		String casDesc = (String)param.get("casDesc");
		if(StringUtils.isEmpty(casDesc)){
			casDesc = "API余额代付";
		}
		
		Map<String, Object> paramMap = new TreeMap<String, Object>();
		paramMap.put("version", "2.1");
		paramMap.put("app_id", param.get("TMercId"));//
		paramMap.put("orgNo", param.get("TTermId"));
		paramMap.put("custId", param.get("TMercId"));
		paramMap.put("custOrdNo", orderNo);
		paramMap.put("casType", "00");
		paramMap.put("casAmt", param.get("netrecAmt"));// 分
		paramMap.put("accountName", param.get("accountName"));
		paramMap.put("cardNo", param.get("cardNo"));
		
		
		String cnapsCode = ObjectUtil.getString(param.get("cnapsCode"));
		
		paramMap.put("cnapsCode", cnapsCode);
		
		
		String signKey = (String) param.get("merKey");
		
		String url = myProp.getProperty("cas_url");
		
		paramMap.put(signKeyName, sign(signKey, paramMap));
		Map<String,Object> resMap = sendHttpRequest(url, paramMap);
		
		Map<String,Object> backMap = new HashMap<String,Object>();
		backMap.put("ordStatus", MsgCT.CAS_ORD_STATUS_06);
		backMap.put("casDesc", resMap.get("msg"));
		
		String status = ObjectUtil.getString(resMap.get("ordStatus"));
		if("08".equals(status)){//失败
			backMap.put("casDesc", "代付失败:" + resMap.get("msg"));
		}
		
		return backMap;
	}

	/**
	 * 提现结果查询
	 * 
	 * @param param
	 * @return
	 * @throws Exception
	 */
	public Map<String, Object> withdrawalQuery(Map<String, Object> param) throws Exception {
		log.info("[Alipay]提现结果查询:" + param);
		// 参数非空验证
		ParamValidate.doing(param, "TMercId", "merKey","casOrdNo");
		String orderNo = (String) param.get("casOrdNo");
		
		Map<String, Object> paramMap = new TreeMap<String, Object>();
		paramMap.put("version", "2.1");
		paramMap.put("app_id", param.get("TMercId"));//
		paramMap.put("orgNo", param.get("TTermId"));
		paramMap.put("custId", param.get("TMercId"));
		paramMap.put("custOrdNo", orderNo);

		String signKey = (String) param.get("merKey");
		
		String url = myProp.getProperty("cas_query");
		
		paramMap.put(signKeyName, sign(signKey, paramMap));
		Map<String,Object> resMap = sendHttpRequest(url, paramMap);
		
		Map<String,Object> backMap = new HashMap<String,Object>();
		backMap.put("ordStatus", MsgCT.CAS_ORD_STATUS_06);
		backMap.put("casDesc", resMap.get("msg"));
		
		String status = ObjectUtil.getString(resMap.get("ordStatus"));
		if("08".equals(status)){//失败
			backMap.put("casDesc", "代付失败:" + resMap.get("msg"));
		} else if("07".equals(status)){
			backMap.put("ordStatus", MsgCT.CAS_ORD_STATUS_07);
		}
		
		return backMap;
	}
	

	public static void main(String[] args) throws Exception {
		AlipayServiceImpl service = new AlipayServiceImpl();
		
		Map<String,Object> merParam = new HashMap<String,Object>();
		
		merParam.put("TMercId", ALI_APP_ID);////////-------------
		merParam.put("TTermId", "");
		merParam.put("merKey", "");
//		merParam.put("merKey", ALI_PRV_DEFULT); //test
		merParam.put("merKeyCV", "");
		
		
		{
			// 支付
			Map<String, Object> param = new HashMap<String, Object>();
			param.put("rtrcod", "pay");
			
			param.putAll(merParam);
			
			param.put("payAmt", "1008");
//			param.put("payType", "07");
//			param.put("rateType", "0506");
			param.put("rateType", "0502");
			param.put("goodsName", "女T恤4");
			param.put("prdOrdNo", DateUtils.getCurrentDateTime() + StringUtil.getRandomNum(6));
//			Map<String, Object> resMap = service.execute(param);
//			System.out.println("返回结果:" + resMap);
		}

		{
			// 订单状态查询
			Map<String, Object> param = new HashMap<String, Object>();
			param.put("rtrcod", TranCode.TRAN_PAY_QUERY);
			
			param.putAll(merParam);
			
			param.put("prdOrdNo", "20180921095940509592");
			Map<String, Object> resMap = service.execute(param);
			System.out.println("返回结果:" + resMap);
		}

		{
			// 提现
			Map<String, Object> param = new HashMap<String, Object>();
			param.put("rtrcod", "withdrawal");
			
			param.putAll(merParam);
			
			
			
			param.put("netrecAmt", "100");
			param.put("casOrdNo", System.currentTimeMillis() + "");
			param.put("accountName", "测试");
			param.put("cardNo", "6228480328592378471");
			param.put("bankName", "中国农业银行");
			
//			param.put("bankName","");
//			param.put("bankPro","浙江省");
//			param.put("bankCity","杭州市");
//			param.put("subBranch","中国农业银行杭州文新路支行");
//			param.put("cnapsCode","103331000074");
			
//			Map<String, Object> resMap = service.execute(param);
//			System.out.println("返回结果:" + resMap);
		}
		{
			// 提现查询
			Map<String, Object> param = new HashMap<String, Object>();
			param.put("rtrcod", TranCode.TRAN_WITHDRAWAL_QUERY);
			
			param.putAll(merParam);
			
//			merParam.put("TMercId", "9000000");
//			merParam.put("TTermId", "9000000");
//			merParam.put("merKey", "3lu4L2f93X21Y5Ok36HD");
//			merParam.put("merKeyCV", "8800008501797");
			
			param.put("casOrdNo", "1519811576373");
			
//			Map<String, Object> resMap = service.execute(param);
//			System.out.println("返回结果:" + resMap);
		}
	}

}
